home *** CD-ROM | disk | FTP | other *** search
- /*
- Simple on-hour no-brainer program to demonstrate how to smoothly scroll a
- 4-plane 16 color (EGA, VGA, SVGA up to 800x600) video screen smoothly.
- Moves the image on the screen up/down by n scan lines at a time using the
- hardware latches and string instructions to move 8 pixels at a time as fast
- as the video hardware can manage.
-
- Takes up to 2 cmd-line parameters.
- The first specifies the video mode:
- 0 = 320x200 16 color
- 1 = 640x200 16 color
- 2 = 640x350 16 color
- 3 = 640x480 2 color
- other = 640x480 16 color (default).
-
- The second specifies the direction to scroll:
- + = scroll up
- - = scroll down
-
- In some video modes or when scrolling down, the last scan line of the
- text used as a demo display will bleed up or down the screen. The solution
- to this problem in your own programs is to keep about one character line
- worth of data cleared to the background color (at the bottom for scrolling
- up, top for scrolling down).
-
- August 20 1992.
- Joe Slayton - CIS ID 70363,2213
-
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <dos.h>
- #include <conio.h>
-
- /*-------------------------------------------------------------------------*/
-
- void SmoothScroll(unsigned nLines, unsigned LinesPer,
- unsigned ScrWidth, unsigned ScrHeight,
- unsigned ScrollUp)
- /*
- Smoothly scrolls the EGA/VGA 16 color screens up or down nLines, moving
- every LinesPer scan lines. Moves all of the pixels on the screen except
- for the top or bottom nLines on the screen. This code also works on the
- VGA and MCGA 640x480 2 color mode (this mode is exactly the same as the
- 16-color modes but with 3 planes disabled).
- ScrWidth is the width of the screen in pixels (320, 640, 800, etc.);
- ScrHeight is the height of the screen in scan lines (200, 350, 480, etc.).
- ScrollUp tells whether to scroll up or down (0 = down, <> 0 = up).
- */
- {
-
- unsigned MoveSize; /* the size of the data block to move */
- unsigned MoveFrom; /* index of scan line start to move from */
- unsigned MoveTo; /* index of scan line to move data to */
-
- /* set up video hardware for speedy copying */
- outport(0x03CE, 5); /* mode control register (5) */
- outport(0x03CF, 1); /* r/w mode 00 01 (read 0, write 1) */
-
- /* convert screen width from pixels to bytes */
- ScrWidth >>= 3;
-
- /* figure how much data to move for each scroll */
- MoveSize = ScrWidth * (ScrHeight - nLines);
-
- /* figure starting and stopping addresses */
- if (ScrollUp) {
- MoveFrom = ScrWidth * LinesPer;
- MoveTo = 0;
- } /* if */
- else {
- MoveFrom = MoveSize + 0;
- MoveTo = MoveSize + ScrWidth * LinesPer;
- } /* else */
-
- /* while still scan lines left to process */
- do {
-
- /* scroll whole screen block in direction required */
- asm {
-
- push ds /* save DS for a moment */
- push si /* save register variables */
- push di
-
- mov ax, 0xA000 /* both source & dest segs are at screen mem */
- mov ds, ax /* set up source pointer */
- mov si, MoveFrom
- mov es, ax /* set up dest pointer */
- mov di, MoveTo
-
- mov cx, MoveSize /* # bytes to move */
-
- cld /* set up for FORWARD move in memory */
-
- cmp ScrollUp, 0 /* check if scrolling up */
-
- jne Forward /* just leave the dir flag the way it was */
-
- std /* do move BACKWARD through memory */
-
- }
- Forward:
- asm {
-
- rep movsb /* do BYTE-ORIENTED move */
-
- cld /* reset in case anyone expects forward moves */
-
- pop di /* restore register variables */
- pop si
- pop ds /* get DS back again */
-
- }
-
- /* one less line to process */
- nLines -= LinesPer;
-
- } while (nLines > 0);
-
- /* reset video hardware to default state */
- outport(0x03CE, 5); /* mode control register (5) */
- outport(0x03CF, 0); /* back to default of 0 */
-
- } /* SmoothScroll */
-
- /*-------------------------------------------------------------------------*/
-
- main(int argc, char *argv[])
- {
-
- int I, J; /* loop counters for character output */
- int Width; /* width of screen in pixels */
- int Height; /* height of screen in pixels */
- int ScrollUp = 1; /* scroll up or down */
- int CharHeight = 16; /* size of character box */
- struct REGPACK Regs; /* registers for INT 0x10 operation */
-
- /* check for scrolling up or down */
- if (argc >= 3) {
- ScrollUp = (argv[2][0] == '+') ? 0 : (argv[2][0] == '+') ? 1 : ScrollUp;
- } /* if */
-
- /* select video mode to use based on command-line arg */
- I = -1;
- if (argc >= 2) {
- I = argv[1][0] - '0';
- } /* if */
-
- /* set up correct video mode */
- switch (I) {
- case 0 : Regs.r_ax = 0x000D; /* 320x200 16 color */
- Width = 320; Height = 200; CharHeight = 8; break;
- case 1 : Regs.r_ax = 0x000E; /* 640x200 16 color */
- Width = 640; Height = 200; CharHeight = 8; break;
- case 2 : Regs.r_ax = 0x0010; /* 640x350 16 color */
- Width = 640; Height = 350; CharHeight = 14; break;
- case 3 : Regs.r_ax = 0x0011; /* 640x480 2 color */
- Width = 640; Height = 480; CharHeight = 16; break;
- default : Regs.r_ax = 0x0012; /* 640x480 16 color */
- Width = 640; Height = 480; CharHeight = 16; break;
- } /* switch */
-
- /* turn on graphics mode */
- intr(0x10, &Regs);
-
- /* draw initial 10 lines of text garbage on the screen */
- for (I = 0; I < 80 * 10; I++) {
- fputc(32 + rand() % 26, stdout);
- } /* for */
-
- do {
-
- /* Draw some more text garbage */
- J = rand() % 20;
- for (I = 0; I < J; I++) {
- fputc(32 + rand() % 26, stdout);
- } /* for */
-
- /* scroll up a stock VGA character height, one at a time */
- SmoothScroll(CharHeight, 1, Width, Height, ScrollUp);
-
- /* until user hits a key */
- } while (!kbhit());
-
- /* return to 80x25 color text mode */
- Regs.r_ax = 0x0003;
- intr(0x10, &Regs);
-
- return 0;
-
- } /* main */
-